package com.moorecat.app.service;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Service;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import com.moorecat.MooerApplication;
import com.moorecat.domain.ResBean;
import com.moorecat.domain.ServiceUrl;
import com.moorecat.http.HttpUtils;
import com.moorecat.utils.UtilTools;

/**
 * 进行定位的相关操作
 * 
 * @author pengfei.xu
 * @version V1.0 创建时间：2011-4-29 上午09:32:40
 */
public class LocationService extends Service {

	private static final String TAG = "LocationService";

	private Location currentLocation;

	private LocationManager locationManager;

	private Criteria criteria;

	private String provider = null;

	private MooerApplication application;

	private double latitude, longitude;

	public final static double latitude_change = -0.00186416629791;

	public final static double longitude_change = 0.00491628341675;

	private LocationListener networkListener, gpsListener;

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "locationService onBind");
		return mBinder;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		application = (MooerApplication) getApplication();
		locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);// 设置为最大精度
		criteria.setAltitudeRequired(false);// 不要求海拔信息
		criteria.setBearingRequired(false);// 不要求方位信息
		criteria.setCostAllowed(true);// 是否允许付费
		criteria.setPowerRequirement(Criteria.POWER_LOW);// 对电量的要求

		provider = locationManager.getBestProvider(criteria, true);
		Log.i(TAG, "provider:" + provider);
		if (provider == null) {
			provider = LocationManager.GPS_PROVIDER;
		}
		currentLocation = locationManager.getLastKnownLocation(provider);
		if (currentLocation != null) {
			latitude = UtilTools.round(currentLocation.getLatitude(), 5); // 纬度
			longitude = UtilTools.round(currentLocation.getLongitude(), 5); // 经度
		} else {
			Log.i(TAG, "GPS有问题啊，location一直为null...");
			provider = LocationManager.NETWORK_PROVIDER;
			currentLocation = locationManager.getLastKnownLocation(provider);
			if (currentLocation == null){
               latitude = 0.0;
               longitude = 0.0;
            }else {
			    latitude = UtilTools.round(currentLocation.getLatitude(), 5); // 纬度
			    longitude = UtilTools.round(currentLocation.getLongitude(), 5); // 经度
            }
		}
		if (!(latitude == 0.0 && longitude == 0.0)) {
			Log.i(TAG, "before:" + latitude + "," + longitude);
			latitude = latitude + latitude_change;
			longitude = longitude + longitude_change;
			application.setLatitude(latitude);
			application.setLongitude(longitude);
			Log.i(TAG, "after:" + latitude + "," + longitude);
			new GetDetailLocation().execute(latitude, longitude);
		}

		// 监听位置变化，10秒一次，距离10米以上
		networkListener = new MyLocationListener();
		locationManager.requestLocationUpdates(
				LocationManager.NETWORK_PROVIDER, 3000, 10, networkListener);
		gpsListener = new MyLocationListener();
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				5000, 10, gpsListener);

	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
	}

	@Override
	public void onDestroy() {
		Log.i(TAG, "locationService onDestroy");
		super.onDestroy();
		if (gpsListener != null) {
			locationManager.removeUpdates(gpsListener);
			gpsListener = null;
		}
		if (networkListener != null) {
			locationManager.removeUpdates(networkListener);
			networkListener = null;
		}
	}

	public class GetDetailLocation extends AsyncTask<Double, Integer, String> {

		private boolean isException;

		@Override
		protected String doInBackground(Double... arg0) {
			String url = ServiceUrl.LOCATION_URL + arg0[0] + "," + arg0[1];
			ResBean resBean = HttpUtils.getStream(url);
			Log.i(TAG, resBean.getStatus() + "");
			String json = resBean.getData();
			if (json != null) {
				Log.i(TAG, json);
				try {
					JSONObject jsonObj = new JSONObject(json);
					JSONArray jsonArray = jsonObj.getJSONArray("Placemark");
					for (int i = 0; i < jsonArray.length(); i++) {
						jsonObj = jsonArray.getJSONObject(i);
						// String address = jsonObj.getString("address");
						jsonObj = jsonObj.getJSONObject("AddressDetails")
								.getJSONObject("Country")
								.getJSONObject("AdministrativeArea")
								.getJSONObject("Locality");
						String city = jsonObj.getString("LocalityName");
						if (jsonObj.has("DependentLocality")) {
							String region = jsonObj.getJSONObject(
									"DependentLocality").getString(
									"DependentLocalityName");
							String road = jsonObj
									.getJSONObject("DependentLocality")
									.getJSONObject("Thoroughfare")
									.getString("ThoroughfareName");
							String address = city + region + road;
							Log.i(TAG, "[address][" + address + "]");
							application.setAddress(address);
						} else if (jsonObj.has("Thoroughfare")) {
							String road = jsonObj.getJSONObject("Thoroughfare")
									.getString("ThoroughfareName");
							String address = city + road;
							Log.i(TAG, "[address][" + address + "]");
							application.setAddress(address);
						}

					}
				} catch (JSONException e) {
					Log.e(TAG, "", e);
					isException = true;
				}
			} else {
				isException = true;
			}
			return null;
		}

		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			// if(isException){
			// Geocoder geocoder = new Geocoder(LocationService.this);
			// try {
			// List<Address> list = geocoder.getFromLocation(latitude,
			// longitude, 5);
			// String address =
			// list.get(0).getAddressLine(0)+list.get(0).getAddressLine(1)+list.get(0).getAddressLine(2);
			// System.out.println("address:"+address);
			// application.setAddress(address);
			// } catch (IOException e) {
			// // TODO Auto-generated catch block
			// e.printStackTrace();
			// }
			// }
		}

	}

	private IBinder mBinder = new LocationServiceBinder();

	public class LocationServiceBinder extends Binder {
		public LocationService getService() {
			return LocationService.this;
		}
	}

	public double getLatitude() {
		if (currentLocation != null) {
			return currentLocation.getLatitude();
		}
		return 0.0;
	}

	public double getLongitude() {
		if (currentLocation != null) {
			return currentLocation.getLongitude();
		}
		return 0.0;
	}

	private class MyLocationListener implements LocationListener {
		private static final int CHECK_INTERVAL = 1000 * 30;

		@Override
		public void onLocationChanged(Location location) {
			Log.i(TAG, "<location changed>latitude:" + location.getLatitude()
					+ ";longitude:" + location.getLongitude());
			Log.d(TAG, "Got New Location of provider:" + location.getProvider());
			if (currentLocation != null) {
				if (isBetterLocation(location, currentLocation)) {
					currentLocation = location;
				}
			} else {
				currentLocation = location;
			}
			if (currentLocation == location) {
				latitude = currentLocation.getLatitude() + latitude_change;
				longitude = currentLocation.getLongitude() + longitude_change;
				application.setLatitude(latitude);
				application.setLongitude(longitude);
				Log.i(TAG, "after:" + latitude + "," + longitude);
				new GetDetailLocation().execute(latitude, longitude);
			}
		}

		@Override
		public void onProviderDisabled(String arg0) {
			Log.i(TAG, "<provider disabled>" + arg0);

		}

		@Override
		public void onProviderEnabled(String arg0) {
			Log.i(TAG, "<provider enabled>" + arg0);

		}

		@Override
		public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
			Log.i(TAG, "<status changed>");

		}

		protected boolean isBetterLocation(Location location,
				Location currentBestLocation) {
			if (currentBestLocation == null) {
				// A new location is always better than no location
				return true;
			}

			// Check whether the new location fix is newer or older
			long timeDelta = location.getTime() - currentBestLocation.getTime();
			boolean isSignificantlyNewer = timeDelta > CHECK_INTERVAL;
			boolean isSignificantlyOlder = timeDelta < -CHECK_INTERVAL;
			boolean isNewer = timeDelta > 0;

			// If it's been more than two minutes since the current location,
			// use the new location
			// because the user has likely moved
			if (isSignificantlyNewer) {
				return true;
				// If the new location is more than two minutes older, it must
				// be worse
			} else if (isSignificantlyOlder) {
				return false;
			}

			// Check whether the new location fix is more or less accurate
			int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
					.getAccuracy());
			boolean isLessAccurate = accuracyDelta > 0;
			boolean isMoreAccurate = accuracyDelta < 0;
			boolean isSignificantlyLessAccurate = accuracyDelta > 200;

			// Check if the old and new location are from the same provider
			boolean isFromSameProvider = isSameProvider(location.getProvider(),
					currentBestLocation.getProvider());

			// Determine location quality using a combination of timeliness and
			// accuracy
			if (isMoreAccurate) {
				return true;
			} else if (isNewer && !isLessAccurate) {
				return true;
			} else if (isNewer && !isSignificantlyLessAccurate
					&& isFromSameProvider) {
				return true;
			}
			return false;

		}

		/**
		 * Checks whether two providers are the same
		 */
		private boolean isSameProvider(String provider1, String provider2) {
			if (provider1 == null) {
				return provider2 == null;
			}
			return provider1.equals(provider2);
		}
	}
}
